<template>
  <foreignObject
    :x="x"
    :y="y"
    :width="width"
    :height="height"
    style="font-size: 0"
    class="vc-overflow-visible vc-text-container"
  >
    <div
      ref="textDiv"
      :contenteditable="innerEditable"
      class="vc-whitespace-nowrap vc-inline-block focus:vc-outline-blue vc-rounded-sm vc-transition-all"
      :class="[innerEditable ? '' : readonlyTextClass]"
      :style="[{ 'font-size': fontSize + 'px' }, textStyle, textCssProps || {}]"
      @transitionend="transitionend"
      @dblclick="startEdit"
      @blur="blur"
      @keyup="keyup"
      @mousedown="mousedown"
    ></div>
  </foreignObject>
</template>
<script lang="ts" setup>
import { CSSProperties, nextTick, onMounted, ref, shallowRef, StyleValue, watch } from "vue";
import { TextFontSzie } from "/@/components/common";

const props = withDefaults(
  defineProps<{
    x: number;
    y: number;
    width?: number;
    height?: number;
    editable?: boolean;
    fontSize?: number;
    value: string | number;
    stopPropagation?: boolean;
    //editable为false的情况下text的额外class
    readonlyTextClass?: string;
    textStyle?: string;
    textCssProps?: CSSProperties;
    readonly?: boolean;
  }>(),
  {
    fontSize: TextFontSzie,
    value: "",
    width: 0,
    height: 0,
    stopPropagation: true,
    readonlyTextClass: "",
    editable: undefined,
    textStyle: "",
  }
);
const emits = defineEmits(["update:value", "update:width", "update:height", "update:editable", "blur"]);

const textDiv = shallowRef<HTMLDivElement>();

let isTriggerTextWacth = true;
watch(
  () => props.value,
  (v) => {
    if (!isTriggerTextWacth) return;
    setText(v);
  }
);
onMounted(() => {
  if (props.value) {
    setText(props.value);
  }
});

function mousedown(e: MouseEvent) {
  if (props.stopPropagation) {
    e.stopPropagation();
  }
}

const innerEditable = ref(props.editable || false);
watch(
  () => props.editable,
  (v) => {
    innerEditable.value = !!v;
  }
);
watch(innerEditable, (v) => {
  if (v) {
    nextTick(() => {
      if (textDiv.value) {
        textDiv.value.focus();
      }
    });
  }
});
watch([() => props.textStyle, () => props.textCssProps], () => {
  nextTick(() => {
    if (textDiv.value) {
      resize(textDiv.value);
    }
  });
});

function blur() {
  if (props.editable === undefined) {
    innerEditable.value = false;
  } else {
    emits("update:editable", false);
  }
  emits("blur");
}

function resize(div: HTMLDivElement) {
  emits("update:width", div.offsetWidth);
  emits("update:height", div.offsetHeight);
}

function getText() {
  if (textDiv.value) {
    return textDiv.value.innerText;
  }
}

function setText(text?: string | number) {
  if (text) {
    if (textDiv.value) {
      textDiv.value.innerText = text + "";
      resize(textDiv.value);
    }
  }
}

function keyup(e: KeyboardEvent) {
  resize(e.target as HTMLDivElement);
  isTriggerTextWacth = false;
  emits("update:value", getText());
  //内部改变 不重新触发setText
  nextTick(() => {
    isTriggerTextWacth = true;
  });
}

function startEdit() {
  if (props.readonly) return;
  if (props.editable === undefined) {
    innerEditable.value = true;
  } else {
    emits("update:editable", true);
  }
}

function transitionend() {
  if (textDiv.value) {
    resize(textDiv.value);
  }
}
</script>
